#include "LecteurPhraseAvecTable.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseAvecTable::LecteurPhraseAvecTable(string nomFich) : ls(nomFich), ts() {
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}










////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opAdd() {
// <opAdd> ::= + | -
    if ((ls.getSymCour()=="+") || (ls.getSymCour()=="-"))
        ls.suivant();
    else
        erreur("<opAdd>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opEt() {
// <opEt> ::= et
    if (ls.getSymCour()=="et")
        ls.suivant();
    else
        erreur("<opEt>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opMult() {
// <opMult> ::= * | /
    if ((ls.getSymCour()=="*") || (ls.getSymCour()=="/"))
        ls.suivant();
    else
        erreur("<opMult>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opOu() {
// <opOu> ::= ou
    if (ls.getSymCour()=="ou")
        ls.suivant();
    else
        erreur("<opOu>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opRel(){
// <opRel> ::= == | != | < | <= | > | >=
    if ((ls.getSymCour()=="==" || ls.getSymCour()=="!=" || ls.getSymCour()=="<" || ls.getSymCour()=="<=" || ls.getSymCour()==">" || ls.getSymCour()==">="))
        ls.suivant();
    else
        erreur("<opRel>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opUnaire(){
// <opUnaire> ::= - | non
    if (ls.getSymCour()=="-" || ls.getSymCour()=="non")
        ls.suivant();
    else
        erreur("<opUnitaire>");
}





////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::affectation() {
// <affectation> ::= <variable> = <expBool>
    testerSymCour("<VARIABLE>");
    ts.chercheAjoute(ls.getSymCour());
    ls.suivant();
    sauterSymCour("=");
    expBool();
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::expBool(){
// <expBool> ::= <expBoolEt> { <opOu> <expBoolEt> }
    expBoolEt();
    while (ls.getSymCour()=="ou") {
	opOu();
	expBoolEt();
    }
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::expBoolEt() {
// <expBoolEt> ::= <relation> { <opEt> <relation> }
    relation();
    while (ls.getSymCour()=="et")
    {
        opEt();
        relation();
    }
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::expression() {
// <expression> ::= <terme> { <opAdd> <terme> } | <chaine>
    if (ls.getSymCour()=="<CHAINE>")
        ls.suivant();            
    else
    {
	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-")
        {
		opAdd();
		terme();
	}
    }
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::facteur() {
// <facteur> ::= <entier>  |  <variable>  |  - <facteur>  |  ( <expression> )
	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>") {
		ts.chercheAjoute(ls.getSymCour());
		ls.suivant();
	} else if (ls.getSymCour()=="-" || ls.getSymCour()=="non") {
//		ls.suivant();
                opUnaire();
		facteur();
	} else if (ls.getSymCour()=="(") {
		ls.suivant();
		expression();
		sauterSymCour(")");
	} else
		erreur("<facteur>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::inst() {
// <affectation> | <instLire> | <instEcrire> | <instTq> | <instSi> | <instRepeter>
    if (ls.getSymCour()=="<VARIABLE>")
	affectation();
    else if (ls.getSymCour()=="lire")
        instLire();
    else if (ls.getSymCour()=="ecrire")
        instEcrire();
    else if (ls.getSymCour()=="tantque")
        instTq();
    else if (ls.getSymCour()=="si")
        instSi();
    else if (ls.getSymCour()=="repeter")
        instRepeter();
    else if (ls.getSymCour()=="pour")
        instPour();
    //else
      //  erreur("<inst>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instEcrire() {
// <instEcrire> ::= ecrire ( <chaine> )
    sauterSymCour("ecrire");
    sauterSymCour("(");
    if (ls.getSymCour()=="<CHAINE>")
    {
        ts.chercheAjoute(ls.getSymCour());
        ls.suivant();
        sauterSymCour(")");
    }
    else
    {
        erreur("<CHAINE>");
    }
    
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instLire() {
//    <instLire> ::= lire ( <variable > )
    sauterSymCour("lire");
    sauterSymCour("(");
    if (ls.getSymCour()=="<VARIABLE>")
    {
        ts.chercheAjoute(ls.getSymCour());
        ls.suivant();
        sauterSymCour(")");
    }
    else
    {
        erreur("<VARIABLE>");
    }
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instRepeter() {
// <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> )
    sauterSymCour("repeter");
    seqInst();
    sauterSymCour("jusqua");
    sauterSymCour("(");
    expBool();
    sauterSymCour(")");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instSi() {
// <instSi> ::= si ( <expBool> ) alors <seqInst> { sinonsi ( <expBool> ) alors <sequInst>} [ sinon <seqInst> ] finsi
    sauterSymCour("si");
    sauterSymCour("(");
    expBool();
    sauterSymCour(")");
    sauterSymCour("alors");
    seqInst();
    while (ls.getSymCour()=="sinonsi")
    {
        sauterSymCour("sinonsi");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");
        sauterSymCour("alors");
        seqInst();
    }
    if (ls.getSymCour()=="sinon")
    {
        sauterSymCour("sinon");
        seqInst();
    }
    sauterSymCour("finsi");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instTq() {
// <instTq> ::= tantque ( <expBool> ) <seqInst> fintq
    sauterSymCour("tantque");
    sauterSymCour("(");
    expBool();
    sauterSymCour(")");
    sauterSymCour("faire");
    seqInst();
    sauterSymCour("fintq");
}
////////////////////////////////////////////////////////////////////////////////
    void LecteurPhraseAvecTable::instPour() {
//      <pour>   ::= pour (<affectation>;<expBool>;<affectation>;) <seqInst> finpour
        sauterSymCour("pour");
        sauterSymCour("(");
        affectation();
        sauterSymCour(";");
        expBool();
        sauterSymCour(";");
        affectation();
       // sauterSymCour(";");
        sauterSymCour(")");
        seqInst();
        sauterSymCour("finpour");
        
    }
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::programme() {
// <programme> ::= debut <seqInst> fin <EOF>
	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::relation(){
// <relation> ::= <expression> { <opRel> <expression> }
    expression();
    while (ls.getSymCour()=="==" || ls.getSymCour()=="!=" || ls.getSymCour()=="<" || ls.getSymCour()=="<=" || ls.getSymCour()==">" || ls.getSymCour()==">=")
    {
        opRel();
        expression();
    }
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }
        do {
                inst();
                sauterSymCour(";");
	} while (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="lire" || ls.getSymCour()=="ecrire" || ls.getSymCour()=="tantque" || ls.getSymCour()=="si" || ls.getSymCour()=="repeter" || ls.getSymCour()=="pour");
	// tant que le symbole courant est un debut possible d'instruction...
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::terme() {
// <terme> ::= <facteur> { <opMult> facteur> }
 	facteur();
	while (ls.getSymCour()=="*" || ls.getSymCour()=="/") {
		opMult();
		facteur();
        }
}